//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Policy Injection Application Block
//===============================================================================

using System.Windows.Forms;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.Unity.InterceptionExtension;
using EntLibContrib.PolicyInjection.CallHandlers.Configuration;

namespace EntLibContrib.PolicyInjection.CallHandlers
{
	/// <summary>
	/// An <see cref="ICallHandler"/> that temporarily changes the cursor while the 
	/// next handler is being processed.
	/// </summary>
	[ConfigurationElementType(typeof(CursorCallHandlerData))]
	public class CursorCallHandler : ICallHandler
	{
		#region Fields
		private Cursor cursor;
		private int order;
		#endregion

		#region Properties
		/// <summary>
		/// Gets the Cursor used by this handler.
		/// </summary>
		/// <value>Cursor.</value>
		public Cursor Cursor
		{
			get { return cursor; }
		}
		#endregion

		#region Construction
		/// <summary>
		/// Creates a new <see cref="CursorCallHandler"/>.
		/// </summary>
		/// <param name="cursor">The cursor.</param>
		public CursorCallHandler(Cursor cursor)
		{
			this.cursor = cursor;
		}

		/// <summary>
		/// Creates a new <see cref="CursorCallHandler"/>.
		/// </summary>
		/// <param name="cursor">The cursor.</param>
		/// <param name="order">The order.</param>
		public CursorCallHandler(Cursor cursor, int order)
			: this(cursor)
		{
			this.order = order;
		}
		#endregion

		#region ICallHandler Members
		/// <summary>
		/// Processes the method call.
		/// </summary>
		/// <param name="input"><see cref="IMethodInvocation"/> with information about the call.</param>
		/// <param name="getNext">delegate to call to get the next handler in the pipeline.</param>
		/// <returns>Return value from the target.</returns>
		/// <remarks>This handler changes the current cursor before the call. Whether or not an exception is thrown, it will
		/// reset the Cursor to its previous value before returning.</remarks>
		public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
		{
			IMethodReturn result = null;

			Cursor previousCursor = Cursor.Current;
			Cursor.Current = Cursor;

			try
			{
				result = getNext()(input, getNext);
			}
			finally
			{
				Cursor.Current = previousCursor;
			}

			return result;
		}

		/// <summary>
		/// Order in which the handler will be executed
		/// </summary>
		/// <value></value>
		public int Order
		{
			get
			{
				return order;
			}
			set
			{
				order = value;
			}
		}
		#endregion
	}
}
